package edu.washington.cs.sounddetector.server.testutil;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioFormat.Encoding;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;

import org.junit.Ignore;

import edu.washington.cs.sounddetector.server.api.object.LabeledSound;
import edu.washington.cs.sounddetector.server.api.object.SoundFormat;
import edu.washington.cs.sounddetector.server.testutil.Data.Doorbell;
import edu.washington.cs.sounddetector.server.testutil.Data.Microwave;
import edu.washington.cs.sounddetector.server.testutil.Data.Unknown;

@Ignore
public class Helper
{

    /**
     * Number of training samples per sound.
     */
    private static final int num = 10;

    public static byte[] getBytes(String path) throws IOException, UnsupportedAudioFileException
    {
        File audioFile = new File(path);
        AudioInputStream stream = AudioSystem.getAudioInputStream(audioFile);

        // convert stream to byte array
        long length = stream.getFormat().getFrameSize() * stream.getFrameLength();
        byte[] audioBytes = new byte[(int) length];
        long numBytesRead = 0;
        while (numBytesRead != -1)
        {
            numBytesRead = stream.read(audioBytes);
        }
        stream.close();

        return audioBytes;
    }

    public static SoundFormat getSoundFormat(String path) throws UnsupportedAudioFileException,
            IOException
    {
        AudioFormat format = getAudioFormat(path);
        boolean signed = (format.getEncoding() == Encoding.PCM_SIGNED);
        SoundFormat soundFormat = new SoundFormat(format.getSampleRate(),
                format.getSampleSizeInBits(), format.getChannels(), signed, format.isBigEndian());
        return soundFormat;
    }

    public static AudioFormat getAudioFormat(String path) throws UnsupportedAudioFileException,
            IOException
    {
        AudioFileFormat fileFormat = AudioSystem.getAudioFileFormat(new File(path));
        AudioFormat format = fileFormat.getFormat();
        return format;
    }

    public static List<LabeledSound> getTrainingSounds() throws UnsupportedAudioFileException,
            IOException
    {
        List<LabeledSound> data = new ArrayList<LabeledSound>();
        for (int i = 0; i < num; i++)
        {
            Data.Doorbell doorbellSound = Data.Doorbell.values()[i];
            byte[] sound = Helper.getBytes(doorbellSound.getPath());
            LabeledSound labeledSound = new LabeledSound(Doorbell.soundClass, sound);
            data.add(labeledSound);
        }
        for (int i = 0; i < num; i++)
        {
            Data.Microwave microwaveSound = Data.Microwave.values()[i];
            byte[] sound = Helper.getBytes(microwaveSound.getPath());
            LabeledSound labeledSound = new LabeledSound(Microwave.soundClass, sound);
            data.add(labeledSound);
        }
        for (int i = 0; i < num; i++)
        {
            Data.Unknown unknownSound = Data.Unknown.values()[i];
            byte[] sound = Helper.getBytes(unknownSound.getPath());
            LabeledSound labeledSound = new LabeledSound(Unknown.soundClass, sound);
            data.add(labeledSound);
        }
        return data;
    }

    public static List<LabeledSound> getTestSounds() throws IOException,
            UnsupportedAudioFileException
    {
        List<LabeledSound> data = new ArrayList<LabeledSound>();
        for (int i = num; i < Data.Doorbell.values().length; i++)
        {
            Data.Doorbell doorbellSound = Data.Doorbell.values()[i];
            byte[] sound = Helper.getBytes(doorbellSound.getPath());
            LabeledSound labeledSound = new LabeledSound(Doorbell.soundClass, sound);
            data.add(labeledSound);
        }
        for (int i = num; i < Data.Microwave.values().length; i++)
        {
            Data.Microwave microwaveSound = Data.Microwave.values()[i];
            byte[] sound = Helper.getBytes(microwaveSound.getPath());
            LabeledSound labeledSound = new LabeledSound(Microwave.soundClass, sound);
            data.add(labeledSound);
        }
        for (int i = num; i < Data.Unknown.values().length; i++)
        {
            Data.Unknown unknownSound = Data.Unknown.values()[i];
            byte[] sound = Helper.getBytes(unknownSound.getPath());
            LabeledSound labeledSound = new LabeledSound(Unknown.soundClass, sound);
            data.add(labeledSound);
        }

        return data;
    }

    public static List<LabeledSound> getSmallSetOfSounds() throws IOException,
            UnsupportedAudioFileException
    {
        List<LabeledSound> data = new ArrayList<LabeledSound>();
        for (int i = 0; i < 4; i++)
        {
            Data.Doorbell doorbellSound = Data.Doorbell.values()[i];
            byte[] sound = Helper.getBytes(doorbellSound.getPath());
            LabeledSound labeledSound = new LabeledSound(Doorbell.soundClass, sound);
            data.add(labeledSound);
        }
        return data;
    }
}
